package wsj;

import core.HiddenLayer;
import core.Phone;
import core.Speaker;

import java.io.*;
import java.util.*;

/**
 * Created with IntelliJ IDEA.
 * User: lahiru
 * Date: 5/15/14
 * Time: 5:21 PM
 * To change this template use File | Settings | File Templates.
 */
public class CollectPdfStats {
    private static final int numberOfLayers = 6;
    private static final String hiddenActivationDir = "/media/Bunty/Academic/Research/speaker-effects/hidden-activations/";
    private static final String pdfAlignmentsDir = "/home/lahiru/DevInstall/kaldi_new/kaldi-trunk/egs/wsj/s5/speaker-effects/pdf-alignments/";
    private static final String saveObjects = "/media/Bunty/Academic/Research/speaker-effects/pdfObjects/013";
    private static final String listOfSpeakers = "013";
//    private static Map<Integer,Integer> coverageMap = new HashMap<Integer, Integer>();
//    private static Map<Integer,ArrayList<Integer>> reverseCoverageMap = new HashMap<Integer, ArrayList<Integer>>();
//    private static final String listOfSpeakers = "011 014 016 017 018 019 01b 01d 01f 01j 01k 01m 01p 01q 01u 027 028 02c 02e 204 013 " +
//            "015 01e 01g 01i 01l 01r 01t 01w 01y 01z 020 021 024 026 029 02b 207 208 20c";

    public static void main(String[] args) {
        List<String> speakers = (Arrays.asList(listOfSpeakers.split(" ")));

        for (int i = 1; i <= numberOfLayers; i++) {
            System.out.println(" Start processing the layer " + i);
            HiddenLayer hiddenLayer = new HiddenLayer(i);

            for(String spk:speakers){

                int finalFrameCount = 0;
                Speaker speaker = new Speaker();
                speaker.setId(spk);

                String ha = hiddenActivationDir + "h" + i + "/activations_." + spk + ".ark";
                String pAlignments = pdfAlignmentsDir + "phones." + spk +".ark";

                System.out.println(" Reading the activation file  " + ha + " for the speaker " + spk);
                System.out.println(" phone labels are in  " + pAlignments + " for the speaker " + spk);

                //Read pdf-alignments line by line, file contains a line per utterance.

                try {
                    BufferedReader phonesBr = new BufferedReader(new FileReader(pAlignments));
                    String line;
//                    List<Integer> phoneList = new ArrayList<Integer>();


                    //Now for each utterance read the hidden activations frame by frame.
                    BufferedReader haBr = new BufferedReader(new FileReader(ha));
                    String line1;

                    int utteranceCount = 0;
                    int frameCount = 0;
                    String frameUtterance = "";
                    String utterance = "";


                    //read a line from the pdf-alignments for each frame in the utterance
                    while ((line = phonesBr.readLine()) != null) {
                        String phoneIds[] = line.split(" ");
                        utterance = phoneIds[0];
                        while ((line1 = haBr.readLine()) != null) {

                            String hArray[] = line1.trim().split(" ");

                            if (hArray.length == 3) {  //starting of an utterance
                                utteranceCount = utteranceCount + 1;
                                frameCount = 0;
                                frameUtterance = hArray[0];

                                String tempArray[] = null;
                                String line2 = "";

                                if (!frameUtterance.equalsIgnoreCase(utterance)) {
                                    System.err.println("The frame utterance " + frameUtterance);
                                    System.err.println("The phone utterance " + utterance);

                                    do {
                                        line2 = haBr.readLine();
                                        tempArray = line2.trim().split(" ");

                                    } while (tempArray.length != 3);

                                    System.err.println("The new frame utterance is " + tempArray[0]);

                                }

                            } else if (hArray.length == 2048) {  //intermediate frame
//                                speaker.addFrameStats(phoneList.get(frameCount), hArray);
                                speaker.addFrameStats(Integer.parseInt(phoneIds[frameCount + 1]), hArray);
                                frameCount = frameCount + 1;
                            } else if (hArray.length == 2049) {   //last frame of the utterance
                                speaker.addFrameStats(Integer.parseInt(phoneIds[frameCount + 1]), Arrays.copyOfRange(hArray, 0, hArray.length - 1));
//                                speaker.addFrameStats(phoneList.get(frameCount), Arrays.copyOfRange(hArray, 0, hArray.length - 1));
                                frameCount = frameCount + 1;
                                finalFrameCount = finalFrameCount + frameCount;
                                break;
                            } else {
                                System.err.println("This is not possible " + hArray.length);
                            }
                        }
                    }
                    haBr.close();
                    System.out.println(" The utterance count " + utteranceCount);
                    System.out.println(" The finalFrameCount " + finalFrameCount);

                    phonesBr.close();
                } catch (IOException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }

                //Printout speaker data,
                int totalPhoneCount = 0;
                Map<Integer, Phone> phones = speaker.getPhones();
                for (int pid : phones.keySet()) {
                    Phone phone = phones.get(pid);
                    //phone.averageVector(); //TODO should only do once when finished
                    int count = phone.getCount();
                    totalPhoneCount = totalPhoneCount + count;
//                    System.out.println("phone id " + pid + " count " + count);
                }

                if (totalPhoneCount != finalFrameCount) {
                    System.err.println(" There is a mismatch of frames for the " + speaker.getId());
                } else {
                    System.out.println("Frame counts are matching for the  " + speaker.getId());
                }


                hiddenLayer.getSpeakerList().add(speaker); //add the current speaker to the hidden layer


            }

            //save the hidden layer data
            String location = null;
            try {
                location = saveObjects + "h" + i + ".ser";
                FileOutputStream fileOut =
                        new FileOutputStream(location);
                ObjectOutputStream out = new ObjectOutputStream(fileOut);
                out.writeObject(hiddenLayer);
                out.close();
                fileOut.close();
            } catch (IOException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }
            System.out.println("Serialized data is saved in " + location + " for " + hiddenLayer.getSpeakerList().size() + " speakers ");

            }
        }


    }

//    private static void findPdfCoverage(String spk) {
//        String pAlignments = pdfAlignmentsDir + "phones." + spk +".ark";
//
//        try {
//            BufferedReader mapBr = new BufferedReader(new FileReader(pAlignments));
//            String line;
//            int count = 0;
//            while ((line = mapBr.readLine()) != null) {
//                List<String> pids= Arrays.asList(line.split(" "));
//
//            }
////            ArrayList<Integer> counts = new ArrayList<Integer>(coverageMap.values());
////
////            for(int key : coverageMap.keySet()){
////                int value = coverageMap.get(key);
//////                counts.add(value);
////
////                if(reverseCoverageMap.get(value) == null){
////                    ArrayList<Integer> temp = new ArrayList<Integer>();
////                    temp.add(key);
////                    reverseCoverageMap.put(value,temp);
////                }else{
////                    ArrayList<Integer> temp = reverseCoverageMap.get(value);
////                    temp.add(key);
////                    reverseCoverageMap.put(value, temp);
////                }
////
////            }
////            Collections.sort(counts);
////            Collections.reverse(counts);
////            Set<Integer> tempSet = new HashSet<Integer>(counts);
////            for(int val : tempSet){
////                System.out.println(val + "  " + reverseCoverageMap.get(val) + " " + reverseCoverageMap.get(val).size());
//////                System.out.println(reverseCoverageMap.get(val));
//////                break;
////            }
//
//
//            mapBr.close();
//        } catch (IOException e) {
//            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
//        }
//    }
//}
